package LiuYun

import spinal.core._
import spinal.lib._
/*
class Difftest (commitNum:Int, tlbidxW:Int) extends Bundle{
  val inst  = Vec(new DifftestInstrCommit(tlbidxW), commitNum)
  val excp  = new DifftestExcpEvent()
  val store = new DifftestStoreEvent()
  val load  = new DifftestLoadEvent()
  val csr = new DifftestCSRRegState()
  val reg = Vec(UInt(32.bits), 32)
}
*/
object DifftestConfig{
    var use_difftest = true
}
class DiffInst(tlbidxW:Int) extends Bundle{
  val coreid = Bits(8.bits)
  val index = Bits(8.bits)
  val valid = Bool()
  val pc = UInt(32.bits)
  val instr = Bits(32.bits)
  val skip = Bool()
  val is_TLBFILL = Bool()
  val TLBFILL_index = UInt(tlbidxW.bits)
  val is_CNTinst = Bool()
  val timer_64_value = UInt(64.bits)
  val wen = Bool()
  val wdest = UInt(5.bits)
  val wdata = UInt(32.bits)
  val csr_rstat = Bool()
  val csr_data = UInt(32.bits)
}

class DifftestInstrCommit(tlbidxW:Int) extends BlackBox{
  //addGeneric("tlbidxW", tlbidxW)
  val io = new Bundle {
    val clock = in Bool()
    val diffinst = in(new DiffInst(tlbidxW))
  }

  // Map the clk
  mapCurrentClockDomain(io.clock)
  
  // Remove io_ prefix
  noIoPrefix()
  
  // Function used to rename all signals of the blackbox
  private def renameIO(): Unit = {
    io.flatten.foreach(bt => {
      if(bt.getName().contains("diffinst")) bt.setName(bt.getName().replace("diffinst_", ""))
    })
  }

  // Execute the function renameIO after the creation of the component
  addPrePopTask(() => renameIO())
}

class DiffExcp extends Bundle{
  val coreid = Bits(8.bits)
  val excp_valid = Bool()
  val eret = Bool()
  val intrNo = UInt(11.bits)
  val cause = Bits(6.bits)
  val exceptionPC = UInt(32.bits)
  val exceptionInst = UInt(32.bits)
}

class DifftestExcpEvent extends BlackBox{
  val io = new Bundle {
    val clock = in Bool()
    val diffexcp = in(new DiffExcp)
  }
  // Map the clk
  mapCurrentClockDomain(io.clock)
  
  // Remove io_ prefix
  noIoPrefix()
  
  // Function used to rename all signals of the blackbox
  private def renameIO(): Unit = {
    io.flatten.foreach(bt => {
      if(bt.getName().contains("diffexcp")) bt.setName(bt.getName().replace("diffexcp_", ""))
    })
  }

  // Execute the function renameIO after the creation of the component
  addPrePopTask(() => renameIO())
}

class DiffTrap extends Bundle{
  val coreid = Bits(8.bits)
  val valid = Bool()
  val code = UInt(8.bits)
  val pc = Bits(32.bits)
  val cycleCnt = UInt(64.bits)
  val instrCnt = UInt(64.bits)
}

class DifftestTrapEvent extends BlackBox{
  val io = new Bundle {
    val clock = in Bool()
    val difftrap = in(new DiffTrap)
  }
  // Map the clk
  mapCurrentClockDomain(io.clock)
  
  // Remove io_ prefix
  noIoPrefix()
  
  // Function used to rename all signals of the blackbox
  private def renameIO(): Unit = {
    io.flatten.foreach(bt => {
      if(bt.getName().contains("difftrap")) bt.setName(bt.getName().replace("difftrap_", ""))
    })
  }

  // Execute the function renameIO after the creation of the component
  addPrePopTask(() => renameIO())
}

class DiffStore extends Bundle{
  val coreid = Bits(8.bits)
  val index = Bits(8.bits)
  val valid = Bits(8.bits)
  val storePAddr = UInt(32.bits)
  val storeVAddr = UInt(32.bits)
  val storeData = Bits(32.bits)
}

class DifftestStoreEvent extends BlackBox{
  val io = new Bundle {
    val clock = in Bool()
    val diffstore = in(new DiffStore)
  }
  // Map the clk
  mapCurrentClockDomain(io.clock)
  
  // Remove io_ prefix
  noIoPrefix()
  
  // Function used to rename all signals of the blackbox
  private def renameIO(): Unit = {
    io.flatten.foreach(bt => {
      if(bt.getName().contains("diffstore")) bt.setName(bt.getName().replace("diffstore_", ""))
    })
  }

  // Execute the function renameIO after the creation of the component
  addPrePopTask(() => renameIO())
}

class DiffLoad extends Bundle{
  val coreid = Bits(8.bits)
  val index = Bits(8.bits)
  val valid = Bits(8.bits)
  val paddr = UInt(32.bits)
  val vaddr = UInt(32.bits)
}

class DifftestLoadEvent extends BlackBox{
  val io = new Bundle {
    val clock = in Bool()
    val diffload = in(new DiffLoad)
  }

  // Map the clk
  mapCurrentClockDomain(io.clock)
  
  // Remove io_ prefix
  noIoPrefix()
  
  // Function used to rename all signals of the blackbox
  private def renameIO(): Unit = {
    io.flatten.foreach(bt => {
      if(bt.getName().contains("diffload")) bt.setName(bt.getName().replace("diffload_", ""))
    })
  }

  // Execute the function renameIO after the creation of the component
  addPrePopTask(() => renameIO())
}

class DiffCsrreg extends Bundle{
  val coreid = Bits(8.bits)
  val crmd = UInt(32.bits)
  val prmd = UInt(32.bits)
  val euen = UInt(32.bits)
  val ecfg = UInt(32.bits)
  val estat = UInt(32.bits)
  val era = UInt(32.bits)
  val badv = UInt(32.bits)
  val eentry = UInt(32.bits)
  val tlbidx = UInt(32.bits)
  val tlbehi = UInt(32.bits)
  val tlbelo0 = UInt(32.bits)
  val tlbelo1 = UInt(32.bits)
  val asid = UInt(32.bits)
  val pgdl = UInt(32.bits)
  val pgdh = UInt(32.bits)
  val save0 = UInt(32.bits)
  val save1 = UInt(32.bits)
  val save2 = UInt(32.bits)
  val save3 = UInt(32.bits)
  val tid = UInt(32.bits)
  val tcfg = UInt(32.bits)
  val tval = UInt(32.bits)
  val ticlr = UInt(32.bits)
  val llbctl = UInt(32.bits)
  val tlbrentry = UInt(32.bits)
  val dmw0 = UInt(32.bits)
  val dmw1 = UInt(32.bits)

  def collect(csr:Csr){
        crmd   := csr.crmd.getValue
        prmd   := csr.prmd.getValue
        euen   := csr.euen.getValue
        ecfg   := csr.ecfg.getValue
        estat  := csr.estat.getValue
        era    := csr.era.getValue
        badv   := csr.badv.getValue
        eentry := csr.eentry.getValue
        tlbidx := csr.tlbidx.getValue
        tlbehi := csr.tlbehi.getValue
        tlbelo0 := csr.tlbelo0.getValue
        tlbelo1 := csr.tlbelo1.getValue
        asid   := csr.asid.getValue
        pgdl   := csr.pgdl.getValue
        pgdh   := csr.pgdh.getValue
        save0  := csr.save0.getValue
        save1  := csr.save1.getValue
        save2  := csr.save2.getValue
        save3  := csr.save3.getValue
        tid    := csr.tid.getValue
        tcfg   := csr.tcfg.getValue
        tval := csr.tval.getValue
        ticlr := csr.ticlr.getValue
        llbctl := csr.llbctl.getValue
        tlbrentry := csr.tlbrentry.getValue
        dmw0 := csr.dmw0.getValue
        dmw1 := csr.dmw1.getValue
    }
}

class DifftestCSRRegState extends BlackBox{
  val io = new Bundle {
    val clock = in Bool()
    val diffcsrreg = in(new DiffCsrreg)
  }

  // Map the clk
  mapCurrentClockDomain(io.clock)
  
  // Remove io_ prefix
  noIoPrefix()
  
  // Function used to rename all signals of the blackbox
  private def renameIO(): Unit = {
    io.flatten.foreach(bt => {
      if(bt.getName().contains("diffcsrreg")) bt.setName(bt.getName().replace("diffcsrreg_", ""))
    })
  }

  // Execute the function renameIO after the creation of the component
  addPrePopTask(() => renameIO())
}

class DiffGreg extends Bundle{
  val coreid = Bits(8.bits)
  val gpr = Vec(UInt(32.bits), 32)
}

class DifftestGRegState extends BlackBox{
  val io = new Bundle {
    val clock = in Bool()
    val diffgreg = in(new DiffGreg)
  }

  // Map the clk
  mapCurrentClockDomain(io.clock)
  
  // Remove io_ prefix
  noIoPrefix()
  
  // Function used to rename all signals of the blackbox
  private def renameIO(): Unit = {
    io.flatten.foreach(bt => {
      if(bt.getName().contains("diffgreg")) bt.setName(bt.getName().replace("diffgreg_", ""))
    })
  }

  // Execute the function renameIO after the creation of the component
  addPrePopTask(() => renameIO())
}
